package com.github.zdg.recyclerview.itemdecoration;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.DrawableRes;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.View;


public class GridEdgeDividerDecoration extends RecyclerView.ItemDecoration {
    public static final String TAG = "GridItemDecoration";
    private static final int[] ATTRS = new int[]{
            android.R.attr.listDivider
    };

    public static final int HORIZONTAL = 0;
    public static final int VERTICAL = 1;
    private final SparseIntArray mHorizontalDividerOffsets = new SparseIntArray();
    private final SparseIntArray mVerticalDividerOffsets = new SparseIntArray();
    private Drawable mHorizontalDivider;
    private Drawable mVerticalDivider;
    private final SparseArray<DrawableCreator> mTypeDrawableFactories = new SparseArray<>();
    public static boolean isDebug = false;
    private int margin_hor, margin_ver;
 
    private int mOrientation= VERTICAL;


    public GridEdgeDividerDecoration(Context context) {
        resolveDivider(context);
    }

    public GridEdgeDividerDecoration(int orientation) {
        this.mOrientation = orientation;
    }
    public GridEdgeDividerDecoration(Context context, int orientation, @DrawableRes int verticaldividerid) {
        this(context, orientation, ContextCompat.getDrawable(context, verticaldividerid),ContextCompat.getDrawable(context, verticaldividerid));
    }

    public GridEdgeDividerDecoration(Context context, int orientation, @DrawableRes int verticaldividerid,@DrawableRes int horizontaldividerid) {
        this(context, orientation, ContextCompat.getDrawable(context, verticaldividerid),ContextCompat.getDrawable(context, horizontaldividerid));
    }
    public GridEdgeDividerDecoration(Context context, int orientation, Drawable divider) {
        this(context, orientation, divider,divider);
    }

    public GridEdgeDividerDecoration(Context context, int orientation, Drawable verticalDivider,Drawable horizontalDivider) {
        resolveDivider(context);
        setOrientation(orientation);
        mVerticalDivider = verticalDivider;
        mHorizontalDivider = horizontalDivider;
    }

    private void resolveDivider(Context context) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mVerticalDivider = mHorizontalDivider = a.getDrawable(0);
        a.recycle();
    }
    private Edge edge=new Edge();

    public void setOrientation(int orientation) {
        this.mOrientation = orientation;
    }

    public void setEdge(Edge edge) {
        this.edge = edge;
    }

    public void setMarginOffsets(int hor_margin, int ver_margin) {
        this.margin_hor = hor_margin;
        this.margin_ver = ver_margin;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        RecyclerView.LayoutManager manager = parent.getLayoutManager();
        if (margin_hor > 0 || margin_ver > 0) {
            //
        } else if (manager instanceof LinearLayoutManager) {
            if (mOrientation == VERTICAL) {
                drawVerticalDividers(c, parent);
            } else if (mOrientation == HORIZONTAL) {
                drawHorizontalDividers(c, parent);
            }
        } else {
            drawVerticalDividers(c, parent);
            drawHorizontalDividers(c, parent);
        }


    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int spanCount = getSpanCount(parent);
        int childCount = parent.getAdapter().getItemCount();
        RecyclerView.LayoutManager manager = parent.getLayoutManager();
        int adapterPosition = parent.getChildAdapterPosition(view);
        boolean isFirstRow = isFirstRow(manager, adapterPosition, spanCount, childCount);
        boolean isLastRow = isLastRow(manager, adapterPosition, spanCount, childCount);
        boolean isFirstColumn = isFirstColumn(manager, adapterPosition, spanCount, childCount);
        boolean isLastColumn = isLastColumn(manager, adapterPosition, spanCount, childCount);
        int horizontalOffsets = getHorizontalOffsets(parent, adapterPosition);
        int verticalOffsets = getVerticalOffsets(parent, adapterPosition);
        if (isDebug) {
            Log.e("zoudong", "horizontalOffsets=" + horizontalOffsets + "-->verticalOffsets=" + verticalOffsets);
            Log.e("zoudong", "getItemOffsets-->adapterPosition=" + adapterPosition + " isFirstRow=" + isFirstRow + " isLastRow=" + isLastRow + " isFirstColumn=" + isFirstColumn + " isLastColumn=" + isLastColumn);
        }
        if (mHorizontalDividerOffsets.indexOfKey(adapterPosition) < 0) {
            mHorizontalDividerOffsets.put(adapterPosition, horizontalOffsets);
        }
        if (mVerticalDividerOffsets.indexOfKey(adapterPosition) < 0) {
            mVerticalDividerOffsets.put(adapterPosition, verticalOffsets);
        }
        if (mOrientation == VERTICAL) {
            if (isFirstRow) {  //第一行
                if (edge.isShowEdge(Edge.TOP_EDGE)) outRect.top = verticalOffsets;
                outRect.bottom = verticalOffsets / 2;
            } else if (isLastRow) {  //最后一行
                outRect.top = verticalOffsets / 2;
                if (edge.isShowEdge(Edge.BUTTOM_EDGE)) outRect.bottom = verticalOffsets;
            } else {
                outRect.top = verticalOffsets / 2;
                outRect.bottom = verticalOffsets / 2;
            }
            if (isFirstColumn) {
                if (edge.isShowEdge(Edge.LEFT_EDGE)) outRect.left = horizontalOffsets;
                outRect.right = horizontalOffsets / 2;
            } else if (isLastColumn) {  //最后一列
                outRect.left = horizontalOffsets / 2;
                if (edge.isShowEdge(Edge.RIGHT_EDGE)) outRect.right = horizontalOffsets;
            } else {
                outRect.left = horizontalOffsets / 2;
                outRect.right = horizontalOffsets / 2;
            }
            if (isFirstColumn && isLastColumn) {
                if (edge.isShowEdge(Edge.LEFT_EDGE)) outRect.left = horizontalOffsets;
                if (edge.isShowEdge(Edge.RIGHT_EDGE)) outRect.right = horizontalOffsets;
            }
        } else {  // 水平方向   四边  offset 无效
            if (isFirstColumn) {
                if (edge.isShowEdge(Edge.LEFT_EDGE)) outRect.left = horizontalOffsets;
                outRect.right = horizontalOffsets / 2;
            } else if (isLastColumn) {
                outRect.left = horizontalOffsets / 2;
                if (edge.isShowEdge(Edge.RIGHT_EDGE)) outRect.right = horizontalOffsets;
            } else {
                outRect.left = horizontalOffsets / 2;
                outRect.right = horizontalOffsets / 2;
            }
            if (isFirstRow) {
                if (edge.isShowEdge(Edge.TOP_EDGE)) outRect.top = verticalOffsets;
                outRect.bottom = verticalOffsets / 2;
            } else if (isLastRow) {
                outRect.top = verticalOffsets / 2;
                if (edge.isShowEdge(Edge.BUTTOM_EDGE)) outRect.bottom = verticalOffsets;
            } else {
                outRect.top = verticalOffsets / 2;
                outRect.bottom = verticalOffsets / 2;
            }
            if (isFirstRow && isLastRow) {
                if (edge.isShowEdge(Edge.TOP_EDGE)) outRect.top = verticalOffsets;
                if (edge.isShowEdge(Edge.BUTTOM_EDGE)) outRect.bottom = verticalOffsets;
            }
        }

        if (isDebug) Log.e(TAG, "outRect" + adapterPosition + outRect.toString());
    }

    private void drawVerticalDividers(Canvas c, RecyclerView parent) {
        final int spanCount = getSpanCount(parent);
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();
        int itemCount = parent.getAdapter().getItemCount();
        final int childCount = parent.getChildCount();
        RecyclerView.LayoutManager manager = parent.getLayoutManager();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            int adapterPosition = params.getViewAdapterPosition();
            boolean isFirstRow = isFirstRow(manager, adapterPosition, spanCount, itemCount);
            boolean isLastRow = isLastRow(manager, adapterPosition, spanCount, itemCount);
            boolean isFirstColumn = isFirstColumn(manager, adapterPosition, spanCount, itemCount);
            boolean isLastColumn = isLastColumn(manager, adapterPosition, spanCount, itemCount);
           if (isDebug) Log.e("zoudong", "adapterPosition=" + adapterPosition + " isFirstRow=" + isFirstRow + " isLastRow=" + isLastRow + " isFirstColumn=" + isFirstColumn + " isLastColumn=" + isLastColumn);
            final Drawable divider = getVerticalDivider(parent, adapterPosition);
            int intrinsicHeight = divider.getIntrinsicHeight();
            if (edge.isShowEdge(Edge.TOP_EDGE) && isFirstRow) {
                final int off_top = params.topMargin + Math.round(ViewCompat.getTranslationY(child));
                divider.setBounds(left, off_top, right, intrinsicHeight);
                divider.draw(c);
            }
            if (isLastRow && !edge.isShowEdge(Edge.BUTTOM_EDGE)) {
                return;
            }
            final int top = child.getBottom() + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child));
            final int bottom = top + intrinsicHeight;

            mVerticalDividerOffsets.put(adapterPosition, intrinsicHeight);
//            Log.e("zoudong", "2->left=" + left + "top=" + top + "right=" + right + "bottom=" + bottom);
            divider.setBounds(left, top, right, bottom);
            divider.draw(c);
        }
    }

    private void drawHorizontalDividers(Canvas c, RecyclerView parent) {
        final int spanCount = getSpanCount(parent);
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();
        int itemCount = parent.getAdapter().getItemCount();
        RecyclerView.LayoutManager manager = parent.getLayoutManager();
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            final int adapterPosition = params.getViewAdapterPosition();
            final Drawable divider = getHorizontalDivider(parent, adapterPosition);
//            boolean isFirstRow = isFirstRow(adapterPosition, spanCount, childCount);
//            boolean isLastRow = isLastRow(adapterPosition, spanCount, childCount);
            boolean isFirstColumn = isFirstColumn(manager, adapterPosition, spanCount, itemCount);
            boolean isLastColumn = isLastColumn(manager, adapterPosition, spanCount, itemCount);
            if (edge.isShowEdge(Edge.LEFT_EDGE) && isFirstColumn) {
                final int off_left = params.leftMargin + Math.round(ViewCompat.getTranslationX(child));
                divider.setBounds(off_left, top, divider.getIntrinsicHeight(), bottom);
                divider.draw(c);
            }
            if (!edge.isShowEdge(Edge.RIGHT_EDGE) && isLastColumn) {
                return;
            }
            final int off_left = params.leftMargin + Math.round(ViewCompat.getTranslationX(child));
            final int left = child.getRight() + off_left;
            final int right = left + divider.getIntrinsicHeight();

            mHorizontalDividerOffsets.put(adapterPosition, divider.getIntrinsicHeight());
            divider.setBounds(left, top, right, bottom);
            divider.draw(c);
        }
    }


    private Drawable getVerticalDivider(RecyclerView parent, int adapterPosition) {
        RecyclerView.Adapter adapter = parent.getAdapter();
        int itemType = adapter.getItemViewType(adapterPosition);
        DrawableCreator drawableCreator = mTypeDrawableFactories.get(itemType);

        if (drawableCreator != null) {
            return drawableCreator.createVertical(parent, adapterPosition);
        }

        return mVerticalDivider;
    }

    private Drawable getHorizontalDivider(RecyclerView parent, int adapterPosition) {
        RecyclerView.Adapter adapter = parent.getAdapter();
        int itemType = adapter.getItemViewType(adapterPosition);
        DrawableCreator drawableCreator = mTypeDrawableFactories.get(itemType);

        if (drawableCreator != null) {
            return drawableCreator.createHorizontal(parent, adapterPosition);
        }

        return mHorizontalDivider;
    }

    private int getHorizontalOffsets(RecyclerView parent, int adapterPosition) {
        if (margin_hor > 0) {
            return margin_hor;
        }
        Drawable divider = getHorizontalDivider(parent, adapterPosition);
        return divider.getIntrinsicWidth();
    }

    private int getVerticalOffsets(RecyclerView parent, int adapterPosition) {
        if (margin_ver > 0) {
            return margin_ver;
        }
        Drawable divider = getHorizontalDivider(parent, adapterPosition);
        return divider.getIntrinsicHeight();
    }

    private boolean isFirstColumn(RecyclerView.LayoutManager layoutManager, int position, int spanCount, int childCount) {
        if (mOrientation == VERTICAL) {
            if (layoutManager instanceof GridLayoutManager) {
                if (0 == getSpanSizeLookup((GridLayoutManager) layoutManager).getSpanIndex(position, spanCount)) {
                    return true;
                }
            }else if (layoutManager instanceof LinearLayoutManager){
                return true;
            }
        } else {
            if (layoutManager instanceof GridLayoutManager) {
                return 0 == getSpanSizeLookup((GridLayoutManager) layoutManager).getSpanGroupIndex(position, spanCount);
            }else if (layoutManager instanceof LinearLayoutManager){
                return position==0;
            }
        }
        return false;
    }

    private boolean isLastColumn(RecyclerView.LayoutManager layoutManager, int position, int spanCount, int childCount) {
        if (mOrientation == VERTICAL) {
            if (layoutManager instanceof GridLayoutManager) {
                if (getSpanSizeLookup((GridLayoutManager) layoutManager).getSpanSize(position) == spanCount || getSpanSizeLookup((GridLayoutManager) layoutManager).getSpanIndex(position, spanCount) == spanCount - 1) {
                    return true;
                }
            }else if (layoutManager instanceof LinearLayoutManager){
                return true;
            }
        } else {
            if (layoutManager instanceof GridLayoutManager) {
                GridLayoutManager.SpanSizeLookup sizeLookup = getSpanSizeLookup((GridLayoutManager) layoutManager);
                return sizeLookup.getSpanGroupIndex(position, spanCount) == sizeLookup.getSpanGroupIndex(childCount - 1, spanCount);
            }else if (layoutManager instanceof LinearLayoutManager){
                return position==childCount-1;
            }
        }
        return false;
    }

    private boolean isFirstRow(RecyclerView.LayoutManager layoutManager, int position, int spanCount, int childCount) {
        if (mOrientation == VERTICAL) {
            if (layoutManager instanceof GridLayoutManager) {
                return 0 == getSpanSizeLookup((GridLayoutManager) layoutManager).getSpanGroupIndex(position, spanCount);
            } else if (layoutManager instanceof LinearLayoutManager){
                return position==0;
            }
        } else {
            if (layoutManager instanceof GridLayoutManager) {
                if (0 == getSpanSizeLookup((GridLayoutManager) layoutManager).getSpanIndex(position, spanCount)) {
                    return true;
                }
            }else if (layoutManager instanceof LinearLayoutManager){
                return true;
            }
        }
        return false;
    }

    private boolean isLastRow(RecyclerView.LayoutManager layoutManager, int position, int spanCount, int childCount) {
        if (mOrientation == VERTICAL) {
            if (layoutManager instanceof GridLayoutManager) {
                GridLayoutManager.SpanSizeLookup sizeLookup = getSpanSizeLookup((GridLayoutManager) layoutManager);
                return sizeLookup.getSpanGroupIndex(position, spanCount) == sizeLookup.getSpanGroupIndex(childCount - 1, spanCount);
            } if (layoutManager instanceof LinearLayoutManager){
                return position==childCount-1;
            }
        } else {
            if (layoutManager instanceof GridLayoutManager) {
                if (getSpanSizeLookup((GridLayoutManager) layoutManager).getSpanSize(position) == spanCount || getSpanSizeLookup((GridLayoutManager) layoutManager).getSpanIndex(position, spanCount) == (spanCount - 1)) {
                    return true;
                }
            } if (layoutManager instanceof LinearLayoutManager){
                return true;
            }
        }
        return false;
    }

    private GridLayoutManager.SpanSizeLookup getSpanSizeLookup(GridLayoutManager layoutManager) {
        return layoutManager.getSpanSizeLookup();
    }
    private int getSpanCount(RecyclerView parent) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();

        if (layoutManager instanceof GridLayoutManager) {
            return ((GridLayoutManager) layoutManager).getSpanCount();
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            return ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
        } else if (layoutManager instanceof LinearLayoutManager) {
           return  1;
        } else {
            throw new UnsupportedOperationException("the GridDividerItemDecoration can only be used in " +
                    "the RecyclerView which use a GridLayoutManager or StaggeredGridLayoutManager");
        }
    }

    public void registerTypeDrawable(int itemType, DrawableCreator drawableCreator) {
        mTypeDrawableFactories.put(itemType, drawableCreator);
    }

    public Edge getEdge() {
        return edge;
    }

    public interface DrawableCreator {
        Drawable createVertical(RecyclerView parent, int adapterPosition);

        Drawable createHorizontal(RecyclerView parent, int adapterPosition);
    }


}
